import time

from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator

from snippets.models import Snippet, Book, HighScore, Album, Track

from django.contrib.auth.models import User




class TrackListingField(serializers.RelatedField):

    def to_representation(self, value):

        duration = time.strftime('%M:%S', time.gmtime(value.duration))

        return 'Track %d: %s (%s)' % (value.order, value.title, duration)

    def display_value(self, instance):

        return 'Track %s' % (instance.title)

class TrackSerializer(serializers.ModelSerializer):

    class Meta:

        model = Track

        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):

    # tracks = serializers.StringRelatedField(many=True)
    # tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    # tracks = serializers.HyperlinkedRelatedField(
    #     many=True,
    #     read_only=True,
    #     view_name='track-detail'
    # )
    # tracks = serializers.SlugRelatedField(
    #     many=True,
    #     read_only=True,
    #     slug_field='title'
    # )
    # track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')

    tracks = TrackListingField(many=True, read_only=True)

    class Meta:

        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):

        tracks_data = validated_data.pop('tracks')

        album = Album.objects.create(**validated_data)

        for track_data in tracks_data:

            Track.objects.create(album=album, **track_data)

        return album

class EventSerializer(serializers.Serializer):

    name = serializers.CharField()
    room_number = serializers.IntegerField(source=[101, 12, 12])
    date = serializers.DateField()


class DynamicFieldsModelSerializer(serializers.ModelSerializer):

    def __init__(self, *args, **kwargs):
        super().__init__(**kwargs)

        fields = kwargs.pop('fields', None)

        if fields is not None:

            allowed = set(fields)
            existing = set(self.fields)

            for field_name in existing - allowed:

                self.fields.pop(field_name)






class UserSerializer(serializers.ModelSerializer):

    class Meta:

        model = User
        fields = "__all__"



class CreateUserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ['email', 'username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):

        user = User(
            email=validated_data['email'],
            username=validated_data['username']
        )

        user.set_password(validated_data['password'])
        user.save()

        return user


    def to_representation(self, instance):

        print(instance.username)
        
        # return super(CreateUserSerializer, self).to_representation(instance)

        return {"namess": instance.username}


class BookListSerializer(serializers.ListSerializer):


    def create(self, validated_data):

        books = [Book(**item) for item in validated_data]

        return Book.objects.bulk_create(books)

    def update(self, instance, validated_data):

        book_mapping = {book.id: book for book in instance}

        data_mapping = {item['id']: item for item in validated_data}

        ret = []

        for book_id, data in data_mapping.items():

            book = book_mapping.get(book_id, None)
            if book is None:
                ret.append(self.child.create(data))

            else:
                ret.append(self.child.update(book, data))

        for book_id, book in book_mapping.items():

            if book_id not in data_mapping:
                book.delete()

        return ret


class BookSerializer(serializers.Serializer):

    id = serializers.IntegerField()
    name = serializers.CharField(max_length=30, )

    class Meta:

        list_serializer_class = BookListSerializer


class User2Serializer(serializers.HyperlinkedModelSerializer):

    class Meta:

        model = User

        fields = ['url', 'id', 'username', 'email']


class CommentSerializer(serializers.Serializer):

    user = UserSerializer(required=False)
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()



class SnippetSerializer(serializers.HyperlinkedModelSerializer):

    owner = serializers.ReadOnlyField(source='owner.username')

    highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format="html")

    class Meta:

        model = Snippet

        fields = ['id', 'url', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style']



    # id = serializers.IntegerField(read_only=True)
    # title = serializers.CharField(required=False, allow_blank=True, max_length=100)
    # code = serializers.CharField(style={'base_template': 'textarea.html'})
    # linenos = serializers.BooleanField(required=False)
    # language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
    # style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
    #
    # def create(self, validated_data):
    #     """
    #     Create and return a new `Snippet` instance, given the validated data.
    #     """
    #     return Snippet.objects.create(**validated_data)
    #
    # def update(self, instance, validated_data):
    #     """
    #     Update and return an existing `Snippet` instance, given the validated data.
    #     """
    #     instance.title = validated_data.get('title', instance.title)
    #     instance.code = validated_data.get('code', instance.code)
    #     instance.linenos = validated_data.get('linenos', instance.linenos)
    #     instance.language = validated_data.get('language', instance.language)
    #     instance.style = validated_data.get('style', instance.style)
    #     instance.save()
    #
    #     return instance


# BaseSerializer需要自己写下面的东西
class HighScoreSerializer(serializers.BaseSerializer):

    def to_internal_value(self, data):

        score = data.get('score')
        player_name = data.get('player_name')

        if not score:
            raise serializers.ValidationError({
                'score': 'This field is required'
            })

        if not player_name:
            raise serializers.ValidationError({
                'player_name': 'This field is required.'
            })


        if len(player_name) > 10:

            raise serializers.ValidationError({
                'player_name': 'May not be more than 10 characters.'
            })


        return {
            'score': int(score),
            'player_name': player_name
        }

    def to_representation(self, instance):

        return {
            'score': instance.score,
            'player_name': instance.player_name
        }

    def create(self, validated_data):

        return HighScore.objects.create(**validated_data)



